package com.kehutong.common.urlconfig;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.net.ssl.SSLSocketFactory;

import org.coraframework.boot.Application;
import org.coraframework.config.Config;
import org.coraframework.http.HttpClient;
import org.coraframework.json.JSON;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.util.CallBack;
import org.coraframework.util.Objects;

import com.kehutong.common.AccessTokenExpiredException;
import com.kehutong.common.errcode.ErrorCode;
import com.kehutong.common.webchat.XmlUtil;


public abstract class UrlConfig {

	protected final Logger logger = LoggerFactory.getLogger(getClass());
	
	protected UrlConfig() {
	}

	protected UrlConfig(String configName, String name) {
		final Config config = Application.getConfig(configName);
		this.url = config.getString(name);
	}
	
	protected UrlConfig(String configName, String name, CallBack<Config> call) throws Exception {
		final Config config = Application.getConfig(configName);
		this.url = config.getString(name);
		call.call(config);
	}
	
	protected String url;

	public String getUrl() {
		return url;
	}
	
	public String getUrl(String page) {
		return getUrl() + page;
	}
	
	public String getUrl(String page, String...params) {
		if (params.length % 2 != 0) {
			throw new IllegalArgumentException("参数必须是偶数!");
		}
		StringBuilder buf = new StringBuilder();
		buf.append(getUrl()).append(page);
		if (buf.indexOf("?") == -1) {
			buf.append("?");
		} else {
			buf.append("&");
		}
		
		for (int i = 0; i < params.length; i += 2) {
			buf.append(params[i]).append("=").append(params[i + 1]).append('&');
		}
		
		int lastIndex = buf.length() - 1;
		if (buf.charAt(lastIndex) == '&') {
			buf.deleteCharAt(lastIndex);
		}
		
		return buf.toString();
	}
	
	public String getEncodeUrl() {
		return urlEncode(getUrl());
	}
	
	public String getEncodeUrl(String page) {
		return urlEncode(getUrl(page));
	}
	
	public String getEncodeUrl(String page, String...params) {
		return urlEncode(getUrl(page, params));
	}
	
	/**
	 * get请求,返回json
	 * @param page
	 * @param callBack
	 * @return
	 * @throws Exception
	 */
	protected JSONObject get(String page, CallBack<HttpClient> callBack) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		callBack.call(httpClient);

		String text = httpClient.get();
		if (httpClient.getResponseCode() != 200) {
			return httpError(httpClient.getResponseCode(), "http状态错误");
		}
		
		return JSON.parseObject(text);
	}

	public ErrorCode get(String page, CallBack<HttpClient> clientCallBack, CallBack<JSONObject> dataCallBack) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		clientCallBack.call(httpClient);

		String text = httpClient.get();
		final JSONObject rs = JSON.parseObject(text);

		return getErrorCode(page, rs, dataCallBack);
	}

	protected ErrorCode getErrorCode(String page, JSONObject rs, CallBack<JSONObject> dataCallBack) throws Exception{
		ErrorCode errCode = ErrorCode.of(rs, "errcode");
		if (errCode == ErrorCode.WORK_OK) {
			if (Objects.nonNull(dataCallBack)) {
				dataCallBack.call(rs);
			}
		} else if (errCode == ErrorCode.WORK_42001) {
			throw new AccessTokenExpiredException(rs.getString("errmsg"));
		} else {
			logger.error("{}: [errCode:{}, errMsg: {}", page, rs.getIntValue("errcode"), rs.getString("errmsg"));
		}
		return errCode;
	}

	/**
	 * post请求,返回json
	 * @param page
	 * @param client
	 * @return
	 * @throws Exception
	 */
	protected JSONObject post(String page, CallBack<HttpClient> client) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		client.call(httpClient);

		String text = httpClient.post();
		if (httpClient.getResponseCode() != 200) {
			return httpError(httpClient.getResponseCode(), "http状态错误");
		}
		
		return JSON.parseObject(text);
	}

	/**
	 * get请求，返回xml
	 * @param page
	 * @param client
	 * @return
	 * @throws Exception
	 */
	protected JSONObject getXML(String page, CallBack<HttpClient> client) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		client.call(httpClient);

		String text = httpClient.get();
		if (httpClient.getResponseCode() != 200) {
			return httpError(httpClient.getResponseCode(), "http状态错误");
		}
		
		logger.info("{}", text);
		return XmlUtil.xml2JSON(text);
	}
	
	
	/**
	 * post请求，返回xml
	 * @param page
	 * @param client
	 * @return
	 * @throws Exception
	 */
	protected JSONObject postXML(String page, CallBack<HttpClient> client) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		client.call(httpClient);

		String text = httpClient.post();
		if (httpClient.getResponseCode() != 200) {
			return httpError(httpClient.getResponseCode(), "http状态错误");
		}
		
		logger.info("{}", text);
		return XmlUtil.xml2JSON(text);
	}
	
	protected JSONObject postXML(SSLSocketFactory ssfFactory, String page, CallBack<HttpClient> client) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page, ssfFactory);
		client.call(httpClient);

		String text = httpClient.post();
		if (httpClient.getResponseCode() != 200) {
			return httpError(httpClient.getResponseCode(), "http状态错误");
		}
		
		logger.info("{}", text);
		return XmlUtil.xml2JSON(text);
	}
	

	protected String sendFile(String page, File file) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		String text = httpClient.sendFile(file);
		return text ;
	}

	protected String send(String page, CallBack<HttpClient> client) throws Exception {
		final HttpClient httpClient = HttpClient.create(getUrl() + page);
		client.call(httpClient);
		String text = httpClient.post();
		return text ;
	}


	public String urlEncode(String url) {
		try {
			return URLEncoder.encode(url, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}
	
	protected JSONObject httpError(int code, String message) {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("code", code);
		jsonObject.put("message", message);
		
		return jsonObject;
	}

}
